import logging
from datetime import timedelta

from sc_engine.messaging import AppErrorOccurredMessage
from sc_engine.messaging import HeartbeatMessage, HeartbeatResponseMessage 
from sc_engine.apps import messages as msgs
from sc_engine.apps.web import poster_method, retrieval_method

def make_app(app_name, root_config, config):
    root_url = config['root_url']
    retrieval = retrieval_method(root_url + '/retrieval/retrieve_retries')
    poster = poster_method(root_url + '/upload/')

    logger = logging.getLogger(app_name)

    app = WebConsoleApp(app_name, retrieval, poster)

    return {
        AppErrorOccurredMessage: app.log_error,
        HeartbeatMessage : app.heartbeat,
        HeartbeatResponseMessage : app.heartbeat_response,
        msgs.YouTubePartialParseAnnouncement: app.youtube_partial_parse,
        timedelta(seconds=15): app.retry_messages,
    }

class WebConsoleApp(object):
    """Communicate with the engine's web console front-end.

    Will send the necessary messages to the web console, as well as periodically
    receiving the list of retry messages and sending them out.
    """

    def __init__(self, name, retriever, poster):
        self.retriever = retriever
        self.poster = poster
        self.logger = logging.getLogger(name)

    def retry_messages(self):
        messages_to_retry = self.retriever()

        results = []

        self.logger.info("Creating messages to retry: %s" % messages_to_retry)

        for type_name, data in messages_to_retry:
            parts = type_name.split('.')
            module = ".".join(parts[:-1])
            m = __import__( module )
            for comp in parts[1:]:
                m = getattr(m, comp)            

            results.append( m(**data) )

        self.logger.info("Messages created to retry: %s" % results)
        return results
    
    def youtube_partial_parse(self, msg):
        self.poster('youtube_partial_parse', msg.to_dict())

    def heartbeat(self, msg):
        self.poster('heartbeat', msg.to_dict())

    def heartbeat_response(self, msg):
        self.poster('heartbeat_response', msg.to_dict())

    def log_error(self, msg):
        try:
            data = {
                'app_name' : msg.app_name,
                'error_message' : unicode(msg.error),
                'traceback' : msg.traceback,
                'log' : msg.log,
            }

            if msg.message is None:
                data['message_name'] = None
                data['message_data'] = None
            else:
                data['message_name'] = str(type(msg.message))[8:-2]
                data['message_data'] = msg.message.to_dict()

            self.poster('error', data)

        except Exception as e:
            self.logger.exception("Exception when trying to log error to web")

